#ifndef _TABLE_H_
#define _TABLE_H_

#include "global.h"

#define MAX_REF_NUM 256                 // Max refered times allowed.
#define MAX_FUNC_NUM 256                // Max function declaration allowed.
#define MAX_TOKEN_NUM 256               // Max token number allowed.
#define MAX_PARAM_NUM 256               // Max pareameter number allowed.

typedef enum Class {
    GLOBAL_VAR = F_CLASS, GLOBAL_CONST, LOCAL_VAR, LOCAL_CONST, FUNC_RET, FUNC_REG, PARAMETER, TEMP_VAR,
    // Extra Class for the convinence of set_param_for_table().
    C_VAR, C_CONST,
} Class;

typedef enum Type {
    T_INT = F_TYPE, T_FLOAT, T_CHAR, T_VOID,
} Type;

typedef union Value {
    int int_val;
    float float_val;
    char char_val;
} Value;

typedef struct FuncElement {
    char name[MAX_TOKEN_LEN];
    Class clss;
    Type type;
    int param_num;
    Type param_list[MAX_PARAM_NUM];
    int dcl_row;
    int ref_num;
    int ref_row[MAX_REF_NUM];
} FuncElement;

typedef struct NormalElement {
    char name[MAX_TOKEN_LEN];
    Class clss;
    Type type;
    Value value;
    Bool initd;
    FuncElement *scope;
    int dcl_row;
    int ref_num;
    int ref_row[MAX_REF_NUM];
} NormalElement;

// NormalElement.scope == NULL, means scope is global.
extern FuncElement *current_scope;

extern FuncElement func_table[];
extern int func_table_p;                  // Counter and pointer for func_table[]
extern NormalElement normal_table[];
extern int normal_table_p;                // Counter and pointer for normal_talbe[]


extern void enter_normal_element(char *name, Class clss, Type type, Value value, int dcl_row);
extern NormalElement *enter_temp_element();
extern void enter_func_element(char *name, Class clss, Type type, int dcl_row);
extern void enter_func_param(TokenType tt);

extern FuncElement *func_table_lookup(char *tb);
extern NormalElement *normal_table_lookup(char *tb);

extern void update_scope();               // Called when new function is declared
extern void reset_temp_p();               // Reset temp_var_p to 0
extern void table_ref_check();            // Check if there are any elements that are never used.

#endif
